/**
 * @file    rga_converter.cpp
 * @brief   实现RGA功能类初始化并申请dma内存
 * @author  Haozhong Xu
 * @date    2025-05-27
 * @version 1.0
 * 
 * @note    实现构造函数、实现色域转换等对外接口函数
 */

#include "rga/rga_converter.hpp"
#include <cstring>
#include <iostream>

/**
 * @brief 类构造函数，并申请dma连续物理内存
 * 
 * @param width 输入图像的分辨率宽度
 * @param height 输入图像的分辨率高
 */
RGAConverter::RGAConverter(int width, int height)
    : _width(width), _height(height) {
    _src_size = width * height * 2; // YUYV422: 2 bytes per pixel
    _dst_size = width * height * 3; // RGB888: 3 bytes per pixel

    // 分配 DMA 内存
    if (dma_buf_alloc(DMA_HEAP_UNCACHE_PATH, _src_size, &_src_fd, (void**)&_src_buf) < 0 ||
        dma_buf_alloc(DMA_HEAP_UNCACHE_PATH, _dst_size, &_dst_fd, (void**)&_dst_buf) < 0) {
        throw std::runtime_error("DMA buffer allocation failed");
    }

    // 注册给 RGA
    _src_handle = importbuffer_fd(_src_fd, _src_size);
    _dst_handle = importbuffer_fd(_dst_fd, _dst_size);

    if (_src_handle == 0 || _dst_handle == 0) {
        throw std::runtime_error("RGA buffer import failed");
    }

    _src_img = wrapbuffer_handle(_src_handle, _width, _height, RK_FORMAT_YUYV_422);
    _dst_img = wrapbuffer_handle(_dst_handle, _width, _height, RK_FORMAT_RGB_888);
}

RGAConverter::~RGAConverter() {
    if (_src_handle) releasebuffer_handle(_src_handle);
    if (_dst_handle) releasebuffer_handle(_dst_handle);
    if (_src_buf) dma_buf_free(_src_size, &_src_fd, _src_buf);
    if (_dst_buf) dma_buf_free(_dst_size, &_dst_fd, _dst_buf);
}

bool RGAConverter::ConvertYUYVToRGB(const uint8_t* yuyv_data, size_t size) {
    if (!yuyv_data || size != (size_t)_src_size) {
        std::cerr << "Invalid YUYV input data\n";
        return false;
    }

    memcpy(_src_buf, yuyv_data, _src_size);

    if (imcheck(_src_img, _dst_img, {}, {}) != IM_STATUS_NOERROR) {
        std::cerr << "RGA imcheck failed\n";
        return false;
    }

    int ret = imcvtcolor(_src_img, _dst_img, RK_FORMAT_YUYV_422, RK_FORMAT_RGB_888);
    if (ret != IM_STATUS_SUCCESS) {
        std::cerr << "RGA imcvtcolor failed: " << imStrError((IM_STATUS)ret) << "\n";
        return false;
    }

    return true;
}

const uint8_t* RGAConverter::GetRGBData() const {
    return _dst_buf;
}

size_t RGAConverter::GetRGBDataSize() const {
    return _dst_size;
}
